// export const REACT_SUSPENSE_TYPE = Symbol.for("react.suspense");
// React中 export { REACT_SUSPENSE_TYPE as Suspense }
// type: react.suspense

// 在创建fiber的时候
// REACT_SUSPENSE_TYPE 类型
// reactFiber
function createFiberFromTypeAndProps() {
  // case REACT_SUSPENSE_TYPE:
  // return createFiberFromSuspense();
  // SuspenseComponent = 13
  // fiber.elementType = REACT_SUSPENSE_TYPE;
}

// 在 beginWork 中

function beginWork() {
  // case SuspenseComponent:
  // return updateSuspenseComponent(current, workInProgress, renderLanes);
}

// root => 函数组件 mountIndeterminateComponent => resetSuspendedCurrentOnMountInLegacyMode
// childFiber => createFiberFromElement => createFiberFromTypeAndProps
// => createFiberFromSuspense => createFiber(SuspenseComponent)

function resetSuspendedCurrentOnMountInLegacyMode() {}

{
  /* <React.Suspense fallback={<Loading></Loading>}></React.Suspense> */
}

export const DidCapture = 0b000000000000000000010000000;
export const NoFlags = 0b000000000000000000000000000;

// 1. PrimaryChildren  PrimaryTree  mountSuspenseFallbackChildren 更新阶段就是 updateXxx
// 2. FallbackChildren FallbackTree mountSuspensePrimaryChildren

function updateSuspenseComponent(current: any, workInProgress: any, renderLanes: any) {
  // child: xxx fallback:xxx
  const nextProps = workInProgress.pendingProps;
  let showFallback = false; // 显示fallback的组件
  // 如果flags上有这个副作用 什么时候添加的???
  const didSuspend = (workInProgress.flags & DidCapture) !== NoFlags;
  if (didSuspend || shouldRemainOnFallback(current, workInProgress, renderLanes)) {
    // Something in this boundary's subtree already suspended. Switch to
    // rendering the fallback children.
    showFallback = true;
    workInProgress.flags &= ~DidCapture;
  }

  if (current === null) {
    // 初次挂载
    // type: {$$typeof: Symbol(react.lazy), React.lazy()
    const nextPrimaryChildren = nextProps.children;
    // fallback
    const nextFallbackChildren = nextProps.fallback;
    if (showFallback) {
      // Ideally we would model this using a stack.
      // pushFallbackTreeSuspenseHandler(workInProgress)
      return mountSuspenseFallbackChildren();
    } else {
      // pushPrimaryTreeSuspenseHandler(workInProgress);
      return mountSuspensePrimaryChildren();
    }
  } else {
    // 更新
  }
}

// 抛出异常之后 渲染 fallback的组件
function mountSuspenseFallbackChildren() {
  const primaryChildProps = {
    mode: 'hidden',
    // children: primaryChildren, // {$$typeof: Symbol(react.lazy)
  };
  mountWorkInProgressOffscreenFiber();
  // createFiberFromFragment();
}

// loading组件渲染完成之后
// ensureRootIsScheduled() => performConcurrentWorkOnRoot() => workLoopSync
// => 再次调度 => 再到 Symbol(react.suspense) =>
// Symbol(react.suspense) => react.lazy => 得到异步组件
// => 渲染 如果出错了????
// Error Boundaries

function shouldRemainOnFallback(current: any, workInProgress: any, renderLanes: any) {
  return false;
}

// 第一次渲染 里面的异步组件
// React.lazy(() => import('./optimization/components/RenderDemo'));
function mountSuspensePrimaryChildren() {
  // child elementType: Symbol(react.offscreen)
  return mountWorkInProgressOffscreenFiber();
}

function mountWorkInProgressOffscreenFiber() {
  return createFiberFromOffscreen();
}

// export const OffscreenComponent = 22
export const OffscreenVisible = 0b001;
export const OffscreenDetached = 0b010;
function createFiberFromOffscreen() {
  // const fiber = createFiber(OffscreenComponent)
  // fiber.stateNode = {
  //   _visibility: OffscreenVisible,
  //   _pendingVisibility: OffscreenVisible,
  //   detach: () => detachOffscreenInstance(primaryChildInstance),
  //   attach: () => attachOffscreenInstance(primaryChildInstance),
  // };
  // return fiber
}

// console.log(0b001 & 0b010); // 0

// 下次就是这个新创建的fiber
function updateOffscreenComponent(current: any, workInProgress: any, renderLanes: any) {
  const nextIsDetached = (workInProgress.stateNode._pendingVisibility & OffscreenDetached) !== 0;
  if (nextIsDetached) {
  } else {
  }
  // reconcileChildren()
  return workInProgress.child;
}

// 就到了 React.lazy的渲染
// 开始就抛出了一个promise的错误 throw payload._result;
// 渲染终止
// Suspense 捕获错误

// 在beginWork的阶段

// react-reconciler/src/ReactFiberWorkLoop
let _beginWork = () => {
  try {
    return beginWork(); // React.lazy throw error
  } catch (originalError: any) {
    if (
      // xxx
      originalError !== null &&
      typeof originalError === 'object' &&
      typeof originalError.then === 'function'
    ) {
      // 继续 throw到上面 然后就到了 workLoop阶段的处理
      throw originalError;
    }
  }
};

// workLoopSync工作循环
function workLoopSync() {}

function renderRootSync(root: any) {
  try {
    // if (workInProgressSuspendedReason !== NotSuspended && workInProgress !== null) {
    // const thrownValue = workInProgressThrownValue;
    workInProgressSuspendedReason = NotSuspended;
    workInProgressThrownValue = null;
    unwindSuspendedUnitOfWork();
    // }
    // 加上flag之后继续工作循环
    // 再次执行 Symbol(react.suspense) 已经存在 DidCapture
    workLoopSync();
  } catch (thrownValue) {
    handleThrow(root, thrownValue);
  }
}

function unwindSuspendedUnitOfWork() {
  throwException();

  // Return to the normal work loop.
  completeUnitOfWork();
}

function completeUnitOfWork() {
  // uniOfWork Symbol(react.lazy)
  // if ((completedWork.flags & Incomplete) === NoFlags) {
  // } else {
  // }
  // 没有完成
  const next = unwindWork();
}

// ReactFiberUnwindWork
function unwindWork() {
  // 判断tag
  // case SuspenseComponent: {}
  // 这就是 flags
  // if (flags & ShouldCapture) {
  //   workInProgress.flags = (flags & ~ShouldCapture) | DidCapture;
  // }
}

function throwException() {
  // sourceFiber.flags |= Incomplete;
  resetSuspendedComponent();
  // Mark the nearest Suspense boundary to switch to rendering a fallback.

  // Symbol(react.suspense)
  const suspenseBoundary = getSuspenseHandler();
  renderDidSuspend(); // 修改了退出状态
  markSuspenseBoundaryShouldCapture();
}

function resetSuspendedComponent() {}

function renderDidSuspend() {
  // workInProgressRootExitStatus = RootSuspended;
}

export const ShouldCapture = 0b000000000010000000000000000;
// 标记
function markSuspenseBoundaryShouldCapture() {
  // suspenseBoundary.flags |= ShouldCapture;
}

export const SuspenseException = new Error();

const NotSuspended = 0;
const SuspendedOnError = 1;
const SuspendedOnDeprecatedThrowPromise = 4;
let workInProgressThrownValue = null;
let workInProgressSuspendedReason = NotSuspended;
// 处理错误
function handleThrow(root: any, thrownValue: any) {
  // A component threw an exception. Usually this is because it suspended, but
  // it also includes regular program errors.

  if (thrownValue === SuspenseException) {
    // thrown value to be a thenable
    // use api
    thrownValue = getSuspendedThenable();
    // workInProgressSuspendedReason = shouldAttemptToSuspendUntilDataResolves()
    //   ? SuspendedOnData
    //   : SuspendedOnImmediate;
  } else {
    // This is a regular error.
    const isWakeable =
      thrownValue !== null &&
      typeof thrownValue === 'object' &&
      typeof thrownValue.then === 'function';
    workInProgressSuspendedReason = isWakeable
      ? // A wakeable object was thrown by a legacy Suspense implementation.
        // This has slightly different behavior than suspending with `use`.
        SuspendedOnDeprecatedThrowPromise
      : // This is a regular error. If something earlier in the component already
        // suspended, we must clear the thenable state to unblock the work loop.
        SuspendedOnError;
  }

  workInProgressThrownValue = thrownValue;
  // const erroredWork = workInProgress;
  // markComponentRenderStopped();
  markComponentSuspended();
}

// ReactFiberThenable
let suspendedThenable: any = null;
function getSuspendedThenable() {
  // 什么时候赋值的 trackUsedThenable
  const thenable = suspendedThenable;
  suspendedThenable = null;
  return thenable;
}

function shouldAttemptToSuspendUntilDataResolves() {
  const handler = getSuspenseHandler();
}

function createCursor(defaultValue: any) {
  return {
    current: defaultValue,
  };
}
// ReactFiberSuspenseContext
const suspenseHandlerStackCursor = createCursor(null);
export function getSuspenseHandler() {
  return suspenseHandlerStackCursor.current;
}

// ReactFiberHooks()
function use() {
  return trackUsedThenable();
}

let thenableState = null;
function trackUsedThenable() {
  // thenableState = createThenableState();
  const thenable = suspendedThenable;
}

let injectedProfilingHooks: any = null;

// ReactFiberDebToolsHook
// Profiler API hooks
function injectProfilingHooks(profilingHooks: any) {
  injectedProfilingHooks = profilingHooks;
}

function markComponentSuspended() {
  injectedProfilingHooks.markComponentSuspended();
}

// retryTimedOutBoundary
